iT邦幫忙

2023 iThome 鐵人賽

DAY 20
0
DevOps

大家都在用 Terraform 實作 IaC 為什麼不將程式寫得更簡潔易讀呢?系列 第 20

實作 AWS 常用服務之 Terraform 模組系列 - KMS 篇

  • 分享至 

  • xImage
  •  

AWS KMS 模組實作

本篇是實作常用的 AWS KMS 服務之 Terraform 模組,並且會使用到 YAML 資料結構來定義模組的內容,完整的專案程式碼分享在我的 Github 上。

  1. 先定義整個專案檔案結構設定檔 ./configs/kms/keys.yaml、放置 KMS Policy JSON 檔案的目錄 ./configs/kms/policies 和模組 my_kms 的放置位置 modules/my_kms:
├── configs
│   ├── cloudfront
│   │   └── distributions.yaml
│   ├── cloudwatch
│   │   └── loggroups.yaml
│   ├── iam
│   │   ├── assume_role_policies
│   │   ├── policies
│   │   ├── role_policies
│   │   ├── user_policies
│   │   └── iam.yaml
│   ├── kinesis
│   │   ├── policies
│   │   └── streams.yaml
│   ├── kms
│   │   └── keys.yaml
│   ├── s3
│   │   ├── policies
│   │   └── s3.yaml
│   ├── subnet
│   │   └── my-subnets.yaml
│   └── vpc
│       └── my-vpcs.yaml
├── example.tfvars
├── locals.tf
├── main.tf
├── modules
│   ├── my_cloudfront
│   ├── my_cloudwatch
│   ├── my_eips
│   ├── my_eventbridge
│   ├── my_iam
│   ├── my_igw
│   ├── my_instances
│   ├── my_kinesis_stream
│   ├── my_kms
│   │   ├── kms_alias.tf
│   │   ├── kms_key.tf
│   │   ├── outputs.tf
│   │   ├── provider.tf
│   │   └── variables.tf
│   ├── my_nacls
│   ├── my_route_tables
│   ├── my_s3
│   ├── my_subnets
│   └── my_vpc
└── variables.tf
  1. 撰寫 ./configs/kms/keys.yaml 內容來定義 KMS 需要用建立的資源:
kms:
  - alias_name: "alias/<ALIAS_NAME>"
    customer_master_key_spec: "<CUSTOMER_MASTER_KEY_SPEC>"
    enable_key_rotation: <true or false>
    is_enabled: <true or flase>
    key_usage: "SIGN_VERIFY"
    multi_region: <true or false>
    policy_file: "<POLICY_FILE_PATH>"
    tagsName: "<KEY_NAME_WITH_TAG>"
  1. 撰寫 my_kms 模組:
  • ./modules/my_kms/outputs.tf:
output "kms_key_id" {
  value = aws_kms_key.kms
}

output "kms_key_alias" {
  value = aws_kms_alias.kms
}
  • ./modules/my_kms/provider.tf:
provider "aws" {
    region  = var.aws_region
    profile = var.aws_profile
}
  • ./modules/my_kms/variables.tf:
variable "aws_region" {
  description = "AWS region"
  default     = "ap-northeast-1"
}

variable "aws_profile" {
  description = "AWS profile"
  default     = ""
}

variable "project_name" {
  type    = string
  description = "Project name"
  default = ""
}

variable "department_name" {
  type        = string
  description = "Department name"
  default     = "SRE"
}

variable "environment" {
  type    = string
  default = ""
}

variable "kms_path" {
  description = "The path of configuration file"
  default     = ""
}

  • ./modules/my_kms/kms_alias.tf:
resource "aws_kms_alias" "kms" {
  for_each = { for r in local.kms : r.tagsName => r }
  
  name = each.value.alias_name
  target_key_id = aws_kms_key.kms[each.value.tagsName].id
}

  • ./modules/my_kms/kms_key.tf:
locals {
  kms = yamldecode(file("${var.kms_path}"))["kms"]
}

resource "aws_kms_key" "kms" {
  for_each = { for r in local.kms : r.tagsName => r }

  customer_master_key_spec = each.value.customer_master_key_spec
  description              = lookup(each.value, "description", "")
  enable_key_rotation      = each.value.enable_key_rotation
  is_enabled               = each.value.is_enabled
  key_usage                = each.value.key_usage
  multi_region             = each.value.multi_region
  policy                   = file("${each.value.policy_file}")

  tags = {
    Name       = each.value.tagsName
    Department = var.department_name
    Env        = var.environment
    Project    = var.project_name
  }

  tags_all = {
    Name       = each.value.tagsName
    Department = var.department_name
    Env        = var.environment
    Project    = var.project_name
  }
}
  1. 撰寫專案相關程式
  • example.tfvars:
aws_region="ap-northeast-1"
aws_profile="<YOUR_PROFILE>"
project_name="example"
department_name="SRE"
  • main.tf:
terraform {
  required_providers {
    aws = {
      version = "5.15.0"
    }
  }

  backend "s3" {
    bucket                  = "<YOUR_S3_BUCKET_NAME>"
    dynamodb_table          = "<YOUR_DYNAMODB_TABLE_NAME>"
    key                     = "terraform.tfstate"
    region                  = "ap-northeast-1"
    shared_credentials_file = "~/.aws/config"
    profile                 = "<YOUR_PROFILE>"
  }
}

其他模組省略...

# kms
module "kms" {
  aws_profile     = var.aws_profile
  aws_region      = var.aws_region
  department_name = var.department_name
  project_name    = var.project_name
  environment     = var.environment
  kms_path        = "./configs/kms/keys.yaml"

  source = "./modules/my_kms"
}


Terraform 執行計畫

  1. 嘗試建立一個 KMS Distribution 來測試一下模組:
kms:
  - alias_name: "alias/my-key"
    customer_master_key_spec: "RSA_2048"
    enable_key_rotation: true
    is_enabled: true
    key_usage: "SIGN_VERIFY"
    multi_region: false
    policy_file: "./configs/kms/policies/my-key-policy.json"
    tagsName: "my-key"
  1. 於專案目錄下執行 terraform init && terraform plan --out .plan -var-file=example.tfvars 來確認一下結果:

...

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # module.kms.aws_kms_alias.kms["my-key"] will be created
  + resource "aws_kms_alias" "kms" {
      + arn            = (known after apply)
      + id             = (known after apply)
      + name           = "alias/my-key"
      + name_prefix    = (known after apply)
      + target_key_arn = (known after apply)
      + target_key_id  = (known after apply)
    }

  # module.kms.aws_kms_key.kms["my-key"] will be created
  + resource "aws_kms_key" "kms" {
      + arn                                = (known after apply)
      + bypass_policy_lockout_safety_check = false
      + customer_master_key_spec           = "RSA_2048"
      + description                        = (known after apply)
      + enable_key_rotation                = true
      + id                                 = (known after apply)
      + is_enabled                         = true
      + key_id                             = (known after apply)
      + key_usage                          = "SIGN_VERIFY"
      + multi_region                       = false
      + policy                             = jsonencode(
            {
              + Id        = "key-consolepolicy-3"
              + Statement = []
              + Version   = "2012-10-17"
            }
        )
      + tags                               = {
          + "Department" = "SRE"
          + "Env"        = "develop"
          + "Name"       = "my-key"
          + "Project"    = "example"
        }
      + tags_all                           = {
          + "Department" = "SRE"
          + "Env"        = "develop"
          + "Name"       = "my-key"
          + "Project"    = "example"
        }
    }

...

Plan: 49 to add, 0 to change, 0 to destroy.
─────────────────────────────────────────────────────────────────────────────

Saved the plan to: .plan

To perform exactly these actions, run the following command to apply:
    terraform apply ".plan"
Releasing state lock. This may take a few moments...

下一篇文章將會展示實作 AWS MSK 之 Terraform 模組。


上一篇
實作 AWS 常用服務之 Terraform 模組系列 - Kinesis 篇
下一篇
實作 AWS 常用服務之 Terraform 模組系列 - MSK 篇
系列文
大家都在用 Terraform 實作 IaC 為什麼不將程式寫得更簡潔易讀呢?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言